/*
** get_elf.c for ftrace in /home/chris/Rendu/B4/UNIX/pullup-project
** 
** Made by christophe lecointe
** Login   <lecoin_c@epitech.net>
** 
** Started on  Fri Jun 29 14:42:17 2012 christophe lecointe
** Last update Sun Jul  1 09:59:08 2012 christophe lecointe
*/

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include "../includes/elf.h"

static void	abort_elf(t_utils_elf *e)
{
  munmap(e->header, e->fileSize);
  free(e);
}

static int		check_elf(Elf64_Ehdr *e)
{
  if (e->e_ident[EI_MAG0] == ELFMAG0 && e->e_ident[EI_MAG1] == ELFMAG1 &&
      e->e_ident[EI_MAG2] == ELFMAG2 && e->e_ident[EI_MAG3] == ELFMAG3)
    return (0);
  return (-1);
}

static int		get_sections(t_utils_elf *e)
{
  Elf64_Shdr	*strsec;

  if (!e->header->e_shoff || e->header->e_shstrndx == SHN_UNDEF)
    {
      printf("NO SH_OFF!\n");
      return (-1);
    }
  e->sectab = (Elf64_Shdr *)((unsigned long)e->header + e->header->e_shoff);
  strsec = &e->sectab[e->header->e_shstrndx];
  e->strtab = (char *)((unsigned long)e->header + strsec->sh_offset);
  if (!(e->symtab = (Elf64_Sym *)get_section(e, ".symtab", &e->symtabSize)) ||
      !(e->strsymtab = (char *)get_section(e, ".strtab", NULL)))
    return (-2);
  return (0);
}

t_utils_elf	*get_elf(int pid)
{
  t_utils_elf	*elf;
  void		*file;
  int		fileS;

  if ((file = load_file(pid, &fileS)) == NULL)
    {
      printf("Erreur lors de la récupération du binaire.\n");
      return (NULL);
    }
  elf = xmalloc(sizeof(t_utils_elf));
  elf->fileSize = fileS;
  if (check_elf((Elf64_Ehdr *)file))
    {
      abort_elf(elf);
      return (NULL);
    }
  elf->header = file;
  if (get_sections(elf))
    {
      abort_elf(elf);
      printf("Erreur lors de la récupération des informations elf.\n");
      return (NULL);
    }
  return (elf);
}
